// Setup basic express server
const fs = require('fs');
const http = require('http');
const https = require('https');
const express = require('express');
const socketIo = require('socket.io');
const path = require('path');
const selfsigned = require('selfsigned');
const crypto = require('crypto');
// const namespace = require('socket.io/lib/namespace');

const app = express();
// sever version 4.8.1 == client version 3.1.0(socketio and socketio_tls )
console.log('server version: 4.8.1');
console.log('http client version: socketio 3.1.0');
console.log('https client version: socketio_tls 3.1.0');
const httpPort = 3100; //socketio
const httpsPort = 3101; // socketio_tls

// 定义证书和密钥的路径
const certDir = path.join(__dirname, 'certs');
const keyPath = path.join(certDir, 'key.pem');
const certPath = path.join(certDir, 'cert.pem');

// 生成强度满足要求的自签名证书（RSA 2048 / SHA-256，含 SAN）
function generateStrongSelfSigned() {
  const attrs = [{ name: 'commonName', value: 'localhost' }];
  const pems = selfsigned.generate(attrs, {
    days: 365,
    keySize: 2048,
    algorithm: 'sha256',
    extensions: [
      {
        name: 'subjectAltName',
        altNames: [
          { type: 2, value: 'localhost' }, // DNS
          { type: 7, ip: '127.0.0.1' },    // IPv4
          { type: 7, ip: '::1' }           // IPv6
        ]
      }
    ]
  });
  if (!fs.existsSync(certDir)) fs.mkdirSync(certDir, { recursive: true });
  fs.writeFileSync(keyPath, pems.private);
  fs.writeFileSync(certPath, pems.cert);
  return { key: pems.private, cert: pems.cert };
}

// 检查已有密钥是否过弱（RSA < 2048 位）
function isWeakKey(pemBuffer) {
  try {
    const keyObj = crypto.createPrivateKey(pemBuffer);
    if (keyObj.asymmetricKeyType !== 'rsa') return false; // 仅校验 RSA
    const details = keyObj.asymmetricKeyDetails || {};
    return (details.modulusLength || 0) < 2048;
  } catch (e) {
    // 不是有效的私钥或解析失败，则让后续逻辑重新生成
    return true;
  }
}

// 构建 HTTPS 选项：优先使用现有证书；若不存在或过弱则重新生成
let httpsOptions;
if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
  const keyBuf = fs.readFileSync(keyPath);
  const certBuf = fs.readFileSync(certPath);
  if (isWeakKey(keyBuf)) {
    console.warn('检测到弱 RSA 私钥(<2048位)，正在重新生成自签名证书...');
    httpsOptions = generateStrongSelfSigned();
  } else {
    httpsOptions = { key: keyBuf, cert: certBuf };
  }
} else {
  console.warn('未找到证书文件，正在生成自签名证书...');
  httpsOptions = generateStrongSelfSigned();
}

// 强制最低 TLS 版本为 1.2
httpsOptions.minVersion = 'TLSv1.2';
// 创建 HTTP 服务器
const httpServer = http.createServer(app);

// 创建 HTTPS 服务器
const httpsServer = https.createServer(httpsOptions, app);

// 创建 Socket.IO 实例，绑定到 HTTP 和 HTTPS 服务器
const io = socketIo();
io.attach(httpServer);
io.attach(httpsServer);


// Routing
app.use(express.static(path.join(__dirname, 'public')));



// 启动 HTTP 服务器
httpServer.listen(httpPort, () => {
  console.log(`HTTP server listening on port ${httpPort}`);
});

// 启动 HTTPS 服务器
httpsServer.listen(httpsPort, () => {
  console.log(`HTTPS server listening on port ${httpsPort}`);
});


// Chatroom

let numUsers = 0;
let sentMessageCount = 0; // 全局计数器
io.on('connection', (socket) => {
  console.log('a user connected:', socket.id, socket.handshake.url);
  numUsers++;
  console.log('用户连接，当前用户数:', numUsers);

  let addedUser = false;
  socket.emit('login', {"numUsers": numUsers});

  // when the client emits 'new message', this listens and executes
  socket.on('new message', (data) => { 
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', { // broadcast是广播，除了自己以外的所有人
      username: socket.username,
      message: data
    });
  
  });

  // setTimeout(() => {
  //   socket.disconnect(true); // 断开连接
  // }, 5000); 
  
  
  // setInterval(() => {
  //   socket.emit('response', JSON.stringify({ message: 'default namespace 定时服务器响应' }));
  // }, 10000); // 每10秒发送一次
  // // when the client emits 'add user', this listens and executes
  
  
  socket.on('add user', (username) => {
    if (addedUser) return;

    // we store the username in the socket session for this client
    socket.username = username;
    ++numUsers;
    addedUser = true;

    const messages1 = [
      {"message": {"username": "robot", "message": "Welcome to the chat room!"}},
    ]

  //   // 计数发送消息
  //   function sendMessages() {
  //     messages1.forEach(function(msg) {
  //       sentMessageCount++; // 递增计数器

  //       // 深拷贝消息对象，避免修改原始数据
  //       const messageWithCount = JSON.parse(JSON.stringify(msg.message));

  //       // 在消息对象中添加计数属性
  //       messageWithCount.count = sentMessageCount;

  //       // 发送包含计数值的消息
  //       socket.emit("login", messageWithCount);

  //       // // 记录日志
  //       // console.log(`已发送消息数量: ${sentMessageCount}`, messageWithCount);

  //       // 动态输出
  //       process.stdout.write(`已发送消息数量: ${sentMessageCount}\r`);

  //    });
  //  }
  //    setInterval(sendMessages, 100);

    // echo globally (all clients) that a person has connected
    socket.broadcast.emit('user joined', {
      username: socket.username,
      numUsers: numUsers
    });
  });
  socket.on('ack_evt_1', (data, cb) => {
        // 两个参数：null和json串
        cb && cb(null,{ evt: 'ack_evt_1', from: 'server', echo: data });
    });

    socket.on('ack_evt_2', (data, cb) => {
        // 两个参数："abc"和json串
        cb && cb("abc",{ evt: 'ack_evt_2', from: 'server', echo: data });
    });
        // 一个参数：json串
    socket.on('ack_evt_3', (data, cb) => {
        cb && cb({ evt: 'ack_evt_3', from: 'server', echo: data });
    });
    // socket.on('ack_evt_4', (data, cb) => {
    //     cb && cb({ evt: 'ack_evt_4', from: 'server', echo: data });
    // });

    // socket.on('ack_evt_5', (data, cb) => {
    //     cb && cb({ evt: 'ack_evt_5', from: 'server', echo: data });
    // });

    // socket.on('ack_evt_6', (data, cb) => {
    //     cb && cb({ evt: 'ack_evt_6', from: 'server', echo: data });
    // });
    // socket.on('ack_evt_7', (data, cb) => {
    //     cb && cb({ evt: 'ack_evt_7', from: 'server', echo: data });
    // });
  // when the client emits 'typing', we broadcast it to others
  socket.on('typing', () => {
    socket.broadcast.emit('typing', {
      username: socket.username
    });
  });

  // when the client emits 'stop typing', we broadcast it to others
  socket.on('stop typing', () => {
    socket.broadcast.emit('stop typing', {
      username: socket.username
    });
  });


  // when the user disconnects.. perform this
  socket.on('disconnect', () => {
    console.log('user disconnected:', socket.id);
    if (addedUser) {
      --numUsers;
      console.log('用户断开，当前用户数:', numUsers);
      // echo globally that this client has left
      socket.broadcast.emit('user left', {
        username: socket.username,
        numUsers: numUsers
      });
    }
  });
});

// 定义命名空间 'nsp_test'
const nspTest = io.of('/nsp_test');

nspTest.on('connection', (socket) => {
  console.log('a user connected to nsp_test namespace:', socket.id);

  // 示例事件处理
  socket.on('message', (data) => {
    console.log('Received message in nsp_test namespace:', data);
  });
  
  // // 定时发送 'response' 事件
  // setInterval(() => {
  //   socket.emit('response', JSON.stringify({ message: 'nsp_test namespace 定时服务器响应' }));
  // }, 10000); // 每10秒发送一次

  socket.on('disconnect', () => {
    console.log('user disconnected from nsp_test namespace:', socket.id);
  });
});
